package cn.epsilon3.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.epsilon3.exception.Epsilon3ReturnException;

import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @description 断言工具类
 * @author: epsilon3
 * @date: 2023/10/23 22:29
 */
public class AssertUtils {


    /**
     * 断言对象是否为空
     *
     * @param obj              断言对象
     * @param exceptionMessage 异常信息
     * @param <T>              泛型
     * @return 原对象
     */
    public static <T> T isNull(T obj, String exceptionMessage) {
        return Optional.ofNullable(obj).orElseThrow(() -> new Epsilon3ReturnException(exceptionMessage));
    }

    /**
     * 断言对象是否不为空
     *
     * @param obj              断言对象
     * @param exceptionMessage 异常信息
     * @param <T>              泛型
     */
    public static <T> void isNotNull(T obj, String exceptionMessage) {
        if (ObjectUtil.isNotNull(obj)) {
            throw new Epsilon3ReturnException(exceptionMessage);
        }
    }

    /**
     * 断言字符串是否为空
     * null 与 空字符
     *
     * @param str              判断字符串
     * @param exceptionMessage 如果为空 异常信息
     * @return 原字符串
     */
    public static String isBlank(String str, String exceptionMessage) {
        return empty(isNull(str, exceptionMessage)).orElseThrow(() -> new Epsilon3ReturnException(exceptionMessage));
    }

    /**
     * 断言集合是否为空
     * null 与 空字符
     *
     * @param collection       判断集合
     * @param exceptionMessage 如果为空 异常信息
     * @return 原字符串
     */
    public static Collection<?> isEmpty(Collection<?> collection, String exceptionMessage) {
        if (CollectionUtil.isEmpty(collection)) {
            throw new Epsilon3ReturnException(exceptionMessage);
        }
        return collection;
    }

    /**
     * 断言是否为true
     *
     * @param status           判断
     * @param exceptionMessage 如果为false 异常信息
     */
    public static void isTrue(Boolean status, String exceptionMessage) {
        if (!status) {
            throw new Epsilon3ReturnException(exceptionMessage);
        }
    }

    /**
     * 断言是否为true
     * 如果为true时，执行函数
     *
     * @param status   判断
     * @param function 处理函数
     */
    public static void isTrue(Boolean status, Runnable function) {
        if (status) {
            function.run();
        }
    }

    /**
     * 断言是否为true
     * 如果为true时，执行函数
     * 为false时返回错误信息
     *
     * @param status           判断
     * @param exceptionMessage 错误信息
     * @param function         处理函数
     */
    public static void isTrue(Boolean status,
                              String exceptionMessage,
                              Runnable function) {
        if (status) {
            function.run();
        } else {
            throw new Epsilon3ReturnException(exceptionMessage);
        }
    }

    /**
     * 断言是否为true
     * 如果为true时，执行函数
     *
     * @param status   判断
     * @param function 处理函数
     * @return 函数处理值或null
     */
    public static <T> T isTrueRt(Boolean status,
                                 Supplier<T> function) {
        T t = null;
        if (status) {
            t = function.get();
        }
        return t;
    }

    /**
     * 断言是否为true
     * 如果为true时，执行函数
     *
     * @param status       判断
     * @param defaultValue status为false时返回的默认值
     * @param function     处理函数
     * @return 函数处理值或默认值
     */
    public static <T> T isTrueRt(Boolean status,
                                 T defaultValue,
                                 Supplier<T> function) {
        if (status) {
            return function.get();
        }
        return defaultValue;
    }

    /**
     * 断言是否为true
     * 如果为true时，执行函数
     *
     * @param status           判断
     * @param defaultValue     status为false时返回的默认值
     * @param isCheckResult    当函数执行后，是否检查返回值为null（字符串包含空字符校验）
     * @param exceptionMessage 返回值为null时的错误信息
     * @param function         处理函数
     */
    public static <T> T isTrueRt(Boolean status,
                                 T defaultValue,
                                 Boolean isCheckResult,
                                 String exceptionMessage,
                                 Supplier<T> function) {
        if (status) {
            T t = function.get();
            if (isCheckResult) {
                if (t instanceof String) {
                    isBlank((String) t,exceptionMessage);
                } else {
                    isNull(t, exceptionMessage);
                }
            }
            return t;
        }
        return defaultValue;
    }

    /**
     * 断言是否为false
     *
     * @param status           判断
     * @param exceptionMessage 如果为true 异常信息
     */
    public static void isFalse(Boolean status, String exceptionMessage) {
        if (status) {
            throw new Epsilon3ReturnException(exceptionMessage);
        }
    }

    /**
     * 此方法不是断言，不会抛异常，只是为了简化判断，清除if
     * 如果为false时，执行函数
     *
     * @param status   判断
     * @param function 处理函数
     */
    public static void isFalse(Boolean status, Runnable function) {
        if (!status) {
            function.run();
        }
    }

    /**
     * 此方法不是断言，不会抛异常，只是为了简化判断，清除if
     * 如果为false时，执行函数
     *
     * @param status            判断
     * @param defaultValue      为status为true时返回的默认值
     * @param isCheckResultNull 当函数执行后，是否检查返回值为null
     * @param exceptionMessage  返回值为null时的错误信息
     * @param function          处理函数
     */
    public static <T> T isFalseRt(Boolean status,
                                  T defaultValue,
                                  Boolean isCheckResultNull,
                                  String exceptionMessage,
                                  Supplier<T> function) {
        if (!status) {
            T t = function.get();
            return isCheckResultNull ? isNull(t, exceptionMessage) : t;
        }
        return defaultValue;
    }

    /**
     * 断言对象是否为空
     * 为空抛出异常
     * 不为空将打印对象日志信息
     *
     * @param obj              断言对象
     * @param exceptionMessage 异常信息
     * @param logAction        日志操作
     * @param logMessage       日志信息
     * @param <T>              泛型
     * @return 原对象
     */
    public static <T> T isNull(T obj,
                               String exceptionMessage,
                               Consumer<String> logAction,
                               String logMessage) {
        T t = isNull(obj, exceptionMessage);
        logAction.accept(logMessage);
        return t;
    }

    /**
     * 字符串判空字符
     *
     * @param str 判断对象
     * @param <T> 字符
     * @return Optional
     */
    private static <T> Optional<T> empty(T str) {
        return StrUtil.isBlank((CharSequence) str) ? Optional.empty() : Optional.of(str);
    }
}
